#include "Logger.h"
#include <string.h>
#include "LockFile.h"

using namespace std;

Logger *Logger::inst = NULL;
string Logger::cadena = "";
LockFile* Logger::lock = NULL;

Logger& eol (Logger& l) {
	l.log();
	return l;
}

void Logger::log() {
	Logger::log(Logger::cadena);
	Logger::cadena.clear();
}

const std::string Logger::getTimeStamp(){
	time_t rawtime;
	struct tm * timeinfo;
	char buffer [80];

	time ( &rawtime );
	timeinfo = localtime ( &rawtime );
	strftime (buffer,80,"[%d/%m/%y %T]\t",timeinfo);
	std::string mensaje = buffer;

	return mensaje;
}

void Logger::log(std::string msj){
    if(isOpen()){

    	lock->tomarLock();
        //(*logFile) << getTimeStamp()  << " | "<< msj << endl;
    	(*logFile) << getpid() << "|" <<  msj << endl;
        lock->liberarLock();
    }
}

Logger Logger::instancia() {
	if(inst == NULL){
		inst = new Logger();
	}
	return *inst;
}

void Logger::setLogFile(const std::string& path){
    logPath = path;
    if(logFile == NULL) {
    	logFile = new ofstream();
    }

}

int Logger::open(){
    if(logPath.length()>0){
        logFile->open(logPath.c_str());
        if(logFile->fail()){
            delete logFile;
            logFile = NULL;
            return -1;
        }else{
			lock = new LockFile(logPath.c_str(),ESCRITURA);
        }
        return 0;
    }
    else return -2;

}

void Logger::close(){
    if(isOpen()){
        logFile->close();
        delete logFile;
        logFile = NULL;
    }

    if( inst != NULL){
    	delete inst;
    	inst = NULL;

    	delete lock;
    }
}

bool Logger::isOpen(){
    return (logFile != NULL && logFile->is_open());
}

ofstream* Logger::logFile = NULL;
std::string Logger::logPath;

Logger& Logger::operator << (const string &cad) {
	Logger::cadena += cad;
	return *this;
}

Logger& Logger::operator << (const unsigned int num) {
	stringstream ss;
	ss << num;
	Logger::cadena += ss.str();
	return *this;
}

Logger& Logger::operator << (const int num) {
	stringstream ss;
	ss << num;
	Logger::cadena += ss.str();
	return *this;
}

Logger& Logger::operator << (const char * cad) {
	Logger::cadena += cad;
	return *this;
}

Logger& Logger::operator << (const char car) {
	Logger::cadena += car;
	return *this;
}

Logger& Logger::operator << (const off_t num) {
	stringstream ss;
	ss << num;
	Logger::cadena += ss.str();
	return *this;
}

Logger& Logger::operator<< (Logger& ( *pf )(Logger&)) {
	return pf(*this);
}

void Logger::liberar() {
	Logger::close();
	if(Logger::inst)
		delete Logger::inst;
	Logger::inst = NULL;
}
